import { publicThreeClass } from "./publicDeps";
import {
  AnimationMixer,
  AnimationAction,
  LoopOnce,
  DirectionalLight,
  AmbientLight,
  Vector3,
  CatmullRomCurve3,
  BufferGeometry,
  LineBasicMaterial,
  Line,
  DoubleSide,
  Matrix4,
  RepeatWrapping,
  Quaternion,
  MeshLambertMaterial,

  TextureLoader,
  Euler,
  Color,
  CurvePath,
  LineCurve3,
  Mesh,
  MeshBasicMaterial,
  QuadraticBezierCurve3,
  TubeGeometry,
} from "three";
import { cloneDeep } from "lodash-es";
import type { GLTF } from "three/examples/jsm/loaders/GLTFLoader";
const gltfs =
  "https://threejs.org/examples/models/gltf/RobotExpressive/RobotExpressive.glb";
let progress = 0; // 物体运动时在运动路径的初始位置，范围0~1
const velocity = 0.001;

let i = 0;
export class RenGLTFLoader extends publicThreeClass {
  mixer: AnimationMixer;
  curve: any;
  model: any;
  pointsArr: any;
  async init(): Promise<void> {
    const gltf = (await this.deps.gltfLoader.loadAsync(
      // baseUrl + '/models/gltf/RobotExpressive/RobotExpressive.glb',
      gltfs
    )) as GLTF;

    const { gui, camera } = this.deps;
    this.add(new DirectionalLight(0xffffff, 1));
    this.add(new AmbientLight(0xffffff, 1));
    gltf.scene.position.set(100, 100, 100);
    gltf.scene.rotateX(Math.PI * 0.5);
    this.add(gltf.scene);
    this.model = gltf.scene;
    // camera.lookAt(100, 0, 10);
    // this.deps.camera.lookAt(gltf.scene.position)
    // this.deps.camera.position.z = 10;
    console.log("初始化");
    // init animtion
    const states = [
      "Idle",
      "Walking",
      "Running",
      "Dance",
      "Death",
      "Sitting",
      "Standing",
    ];
    const emotes = ["Jump", "Yes", "No", "Wave", "Punch", "ThumbsUp"];

    this.mixer = new AnimationMixer(gltf.scene);
    const actions: { [k: string]: AnimationAction } = {};
    for (let i = 0; i < gltf.animations.length; i++) {
      const clip = gltf.animations[i];
      const action = this.mixer.clipAction(clip);
      actions[clip.name] = action;
      if (emotes.indexOf(clip.name) >= 0 || states.indexOf(clip.name) >= 4) {
        action.clampWhenFinished = true;
        action.loop = LoopOnce;
      }
    }

    let clipAction = actions["Walking"];
    clipAction.play();
    const { renderer } = this.deps;
    const bu = document.getElementById("bu");

    // bu.addEventListener("click", function () {
    //   var i = Math.round(Math.random() * Object.keys(actions).length);
    //   console.log(i);
    //   const str = Object.keys(actions)[i];
    //   clipAction = actions[str];

    //   const obj = {
    //     x: 30,
    //     y: 60,
    //     z: 300,
    //   };
    //   // gui界面上增加交互界面，改变obj对应属性
    //   gui.add(obj, "x", 0, 100);
    //   clipAction.play();
    // });
  this.makeCurve();
    this.addControl();
  //  this.makeCurves();
  }


  initquxian(){
    const p1 = glMatrix.vec3.fromValues(2, 0, 0);
    const p2 = glMatrix.vec3.create();//默认(0,0,0)
    console.log('p2',p2);
    //p1矩阵变换，变换后结果存储在p2
    glMatrix.vec3.transformMat4(p2, p1, modelMatrix);
    console.log('p2', p2);//Float32Array(3) [40, 0, 0]

  }
  makeCurves() {
    // 三维样条曲线
    const path = new CatmullRomCurve3([
      new Vector3(-50, 20, 90),
      new Vector3(-10, 40, 40),
      new Vector3(0, 0, 0),
      new Vector3(60, -60, 0),
      new Vector3(70, 0, 80),
    ]);
    const geometry = new TubeGeometry(path, 200, 5, 30);
    const texLoader = new TextureLoader(); 
    //纹理贴图
    const texture = texLoader.load('https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F4415327a-1d82-4985-8302-44b07a8498c0%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1687512010&t=df81831ff29236e2796899fdcaf43b74');
    //UV坐标U方向阵列模式
    texture.wrapS = RepeatWrapping;
    //纹理沿着管道方向阵列(UV坐标U方向)
    texture.repeat.x = 10;
    const material = new MeshLambertMaterial({
        map:texture,
        side: DoubleSide, //双面显示看到管道内壁
    });
    const mesh = new Mesh(geometry, material);
    this.pointsArr = path.getSpacedPoints(2000);

   this.add(mesh);
  }

  makeCurve() {
    const { scene } = this.deps;
    //Create a closed wavey loop
    this.curve = new CatmullRomCurve3([
      new Vector3(0, 1, 1),
      new Vector3(50, 1, 1),
      new Vector3(0, 1, 50),
    ]);
    this.curve.curveType = "catmullrom";
    this.curve.closed = true; //设置是否闭环
    this.curve.tension = 0.5; //设置线的张力，0为无弧度折线

    // 为曲线添加材质在场景中显示出来，不显示也不会影响运动轨迹，相当于一个Helper
    const points = this.curve.getPoints(50);
    const geometry = new BufferGeometry().setFromPoints(points);
    const material = new LineBasicMaterial({ color: 0x000000 });

    // Create the final object to add to the scene
    const curveObject = new Line(geometry, material);
    this.moveOnCurve()
   //this.initGuandao();
   this.initGuandaos()
    scene.add(curveObject);
  }
  initGuandaos() {
    // 创建多段线条的顶点数据
    let planeMaterial = new MeshBasicMaterial({ color: new Color("red") });
    const p1 = new Vector3(0, 0, 100);
    const p2 = new Vector3(0, 0, 30);
    const p3 = new Vector3(0, 0, 0);
    const p4 = new Vector3(30, 0, 0);
    const p5 = new Vector3(100, 0, 0);

    // 1. 3D直线线段
    const line1 = new LineCurve3(p1, p2);
    // 2. 三维二次贝塞尔曲线
    const curve = new QuadraticBezierCurve3(p2, p3, p4);
    // 3. 3D直线线段
    const line2 = new LineCurve3(p4, p5);

    const CurvePaths = new CurvePath();
    // 三条线拼接为一条曲线
    CurvePaths.curves.push(line1, curve, line2);

    // CurvePath:路径   40：沿着轨迹细分数  2：管道半径   25：管道截面圆细分数
    const geometry = new TubeGeometry(CurvePaths, 50, 2, 25);
    let planes = new Mesh(geometry, planeMaterial); // 设置地面的位置

    this.deps.scene.add(planes);
  }
  initGuandao() {
    // 创建多段线条的顶点数据
    let planeMaterial = new MeshBasicMaterial({ color: new Color("red") });
    const p1 = new Vector3(0, 0, 100);
    const p2 = new Vector3(0, 0, 30);
    const p3 = new Vector3(0, 0, 0);
    const p4 = new Vector3(30, 0, 0);
    const p5 = new Vector3(100, 0, 0);

    // 1. 3D直线线段
    const line1 = new LineCurve3(p1, p2);
    // 2. 三维二次贝塞尔曲线
    const curve = new QuadraticBezierCurve3(p2, p3, p4);
    // 3. 3D直线线段
    const line2 = new LineCurve3(p4, p5);

    const CurvePaths = new CurvePath();
    // 三条线拼接为一条曲线
    CurvePaths.curves.push(line1, curve, line2);

    // CurvePath:路径   40：沿着轨迹细分数  2：管道半径   25：管道截面圆细分数
    const geometry = new TubeGeometry(CurvePaths, 50, 2, 25);
    let planes = new Mesh(geometry, planeMaterial); // 设置地面的位置

    this.deps.scene.add(planes);
  }
  moveOnCurve() {
    const { curve, model } = this;
    const { scene, camera } = this.deps;
    if (curve == null || model == null) {
      console.log("Loading");
    } else {

 
      if (progress > 0 && (progress + velocity)<1) {
        const point = curve.getPointAt(progress); //获取样条曲线指定点坐标
        const pointBox = curve.getPointAt(progress + velocity); //获取样条曲线指定点坐标

        console.log(progress);
        if (point && pointBox) {
          model.position.set(point.x, point.y, point.z);
          //因为这个模型加载进来默认面部是正对Z轴负方向的，所以直接lookAt会导致出现倒着跑的现象，这里用重新设置朝向的方法来解决。

          var targetPos = pointBox; //目标位置点
          var offsetAngle = 0; //目标移动时的朝向偏移

          // //以下代码在多段路径时可重复执行
          var mtx = new Matrix4(); //创建一个4维矩阵
          // .lookAt ( eye : Vector3, target : Vector3, up : Vector3 ) : this,构造一个旋转矩阵，从eye 指向 target，由向量 up 定向。
          mtx.lookAt(model.position.clone(), targetPos, model.up); //设置朝向

          mtx.multiply(
            new Matrix4().makeRotationFromEuler(new Euler(0, offsetAngle, 0))
          );
          var toRot = new Quaternion().setFromRotationMatrix(mtx); //计算出需要进行旋转的四元数值
          model.quaternion.slerp(toRot, 0.2);

          const { x, y, z } = model.position.clone();
       //  camera.position.set(x, y, z + 10);
        }

        progress -= velocity;
      } else {
        progress = 1 - velocity;
      }
    }
  }
  donghua() {
    if (i < this.pointsArr.length - 1) {
      // 渲染循环
      //在渲染循环中累加变化
      const {x,y,z}=this.pointsArr[i]
      this.model.position.set(x,y,z);
      const s=i>100?i-100:0
 
      this.deps.camera.position.copy(this.pointsArr[s]);
      this.deps.camera.lookAt(this.pointsArr[i + 1]);
      i += 1;
    } else {
      i = 0;
    }
  }

  update(): void {
    this.mixer?.update(this.deps.clock.getDelta());
    if (this.model) {
   //   this.donghua()
    this.moveOnCurve();
      //  console.log(this.model.position)
      //  this.orbitControl?.target.set(100,100,100)
    }

    this.orbitControl?.update();
  }

  dispose(): void {
    this.mixer.stopAllAction();
    this.mixer = null;
    this.reset();
  }
}
